using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace GameLib1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            TextureManager.current.Add( "PH", Content.Load<Texture2D>("PH"));
            TextureManager.current.Add("PH2", Content.Load<Texture2D>("PH2"));
            TextureManager.current.Add("MOUSE", Content.Load<Texture2D>("MOUSE"));
            TextureManager.current.Add("Button_Quit", Content.Load<Texture2D>("Button_Quit"));
            TextureManager.current.Add("Button_Options", Content.Load<Texture2D>("Button_Options"));
            TextureManager.current.Add("Button_Start", Content.Load<Texture2D>("Button_Start"));
            TextureManager.current.Add("Button_Level_Editor", Content.Load<Texture2D>("Button_Level_Editor"));
            TextureManager.current.Add("Alien_Creeper", Content.Load<Texture2D>("Alien_Creeper"));
            TextureManager.current.Add("Alien_Overlord", Content.Load<Texture2D>("Alien_Overlord"));
            TextureManager.current.Add("Alien_Soldier", Content.Load<Texture2D>("Alien_Soldier"));
            TextureManager.current.Add("Alien_Swarm", Content.Load<Texture2D>("Alien_Swarm"));
            TextureManager.current.Add("selector", Content.Load<Texture2D>("selector"));

            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();
            graphics.ToggleFullScreen();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        Map MAP;
        GameObject selector = null;

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (StateManager.current.mTransient)
            {
                if (StateManager.current.mState == STATE.QUIT)
                {
                    this.Exit();
                }
                if (StateManager.current.mState == STATE.RESTART)
                {
                    StateManager.current.mCurr = StateManager.current.mPrev;
                    StateManager.current.mState = StateManager.current.mPrev;
                    ObjectManager.current.Clear();
                }
                
                StateManager.current.mState = STATE.GAME;
                StateManager.current.mCurr = STATE.GAME;

                // SWITCH( CURRENT LEVEL ) load level
                /*
                 * LOAD MAP PSEUDO_CODE:
                 * 
                 * Map MAP = new Map( "Map_Level_1" ) ;
                 * 
                 * foreach TILE [] t_array in MAP
                 *  foreach TILE t in t_array
                 *      switch t
                 *          case spawn:
                 *              create thing
                 *          case floor:
                 *              create floor:
                 *          etc..
                 * 
                 */

                switch (StateManager.current.mLevel)
                {
                    case LEVEL.MENU:
                        // initialize level (load map, etc)
                        ObjectManager.current.Clear();
                        Button exit   = (Button)ObjectManager.current.Add(new Button(new Vector2(100, 100), Button.ACTION.EXIT));
                        Button editor = (Button)ObjectManager.current.Add(new Button(new Vector2(200, 100), Button.ACTION.MAP_EDITOR));
                        break;

                    case LEVEL.CREDITS:
                        ObjectManager.current.Clear();
                        break;
                    case LEVEL.LEVEL_SELECT:
                        ObjectManager.current.Clear();
                        break;
                    case LEVEL.GAME_MAPA:
                        ObjectManager.current.Clear();
                        break;
                    case LEVEL.GAME_MAPB:
                        ObjectManager.current.Clear();
                        break;

                    case LEVEL.MAP_EDITOR:
                        ObjectManager.current.Clear();
                        MAP = new Map(null);

                        MAP.Create(20, 15, Map.TILE.FLOOR_GRASS);


                        selector = ObjectManager.current.Add("selector");

                        break;

                    default:
                        System.Console.Error.Write("How the foobar did we get here?!?!?");
                        break;
                }


                StateManager.current.mTransient = false;
            }
            else
            {
                if (StateManager.current.mState != StateManager.current.mCurr)
                {
                    StateManager.current.mTransient = true;
                    StateManager.current.mPrev = StateManager.current.mCurr;
                    StateManager.current.mCurr = StateManager.current.mState;
                }
                else
                {
                    // current level logic

                    switch (StateManager.current.mLevel)
                    {
                        case LEVEL.MENU:

                            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                                StateManager.current.mState = STATE.QUIT;

                            break;
                        case LEVEL.CREDITS:
                            break;

                        case LEVEL.LEVEL_SELECT:
                            break;

                        case LEVEL.GAME_MAPA:
                            break;

                        case LEVEL.GAME_MAPB:
                            break;

                        case LEVEL.MAP_EDITOR:

                            selector.mPos = new Vector2((int)((Mouse.GetState().X - Camera.Position.X) / 32) * 32, (int)((Mouse.GetState().Y - Camera.Position.Y) / 32) * 32);

                            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                                StateManager.current.mState = STATE.QUIT;
                            break;

                        default:
                            System.Console.Error.Write("How the foobar did we get here?!?!?");
                            break;
                    }



                    ObjectManager.current.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
                }
            }

            Camera.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            if (MAP != null)
            {
                spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullCounterClockwise, null, Camera.Transform);
                for (int x = 0; x < MAP.mWidth; x++)
                {
                    for (int y = 0; y < MAP.mHeight; y++)
                    {
                        switch (MAP[x, y])
                        {
                            case Map.TILE.FLOOR_GRASS:
                            case Map.TILE.FLOOR_STONE:
                                spriteBatch.Draw(TextureManager.current.texture("PH"), new Vector2(x * 32, y * 32), Color.White);
                                break;
                            default:
                                break;
                        }
                    }
                }
                spriteBatch.End();
            }
            ObjectManager.current.Draw(spriteBatch);

            spriteBatch.Begin();
            spriteBatch.Draw(TextureManager.current.texture("MOUSE"), new Vector2(Mouse.GetState().X, Mouse.GetState().Y), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
